/******************************************************************************
 **
 **  COPYRIGHT (C) 2002 Intel Corporation.
 **
 **  This software as well as the software described in it is furnished under
 **  license and may only be used or copied in accordance with the terms of the
 **  license. The information in this file is furnished for informational use
 **  only, is subject to change without notice, and should not be construed as
 **  a commitment by Intel Corporation. Intel Corporation assumes no
 **  responsibility or liability for any errors or inaccuracies that may appear
 **  in this document or any software that may be provided in association with
 **  this document.
 **  Except as permitted by such license, no part of this document may be
 **  reproduced, stored in a retrieval system, or transmitted in any form or by
 **  any means without the express written consent of Intel Corporation.
 **
 **  FILENAME:       KeypadTest.c
 **
 **  PURPOSE:        This file contains the Bulverde Keypad POST code for
 **                  the Intel(r) XScale(tm) Microarchitecture.
 **
 **  LAST MODIFIED:  $Modtime: 9/20/02 9:52a $
 ******************************************************************************/

/*
 *******************************************************************************
 *   HEADER FILES
 *******************************************************************************
 */
#include "arch.h"
#include "mhn-regs.h"
#include "KeypadTest.h"
#include "util.h"
#include "types.h"
#include "xllp_mfp_proc_L_LV.h"
#include "xllp_mfp_plat_L_LV.h"
#include "xllp_mfp_rm.h"
#include "xllp_keypad_proc.h"

#define CONFIG_CPU_MONAHANS_LV
/*
   Scan code definitions.
   These will not change; rather, the method of calculating them will change.
   They must be 8-bit unsigned values
   */
#define     XLLP_KP_SC_NO_KEY               0xFF
#define     XLLP_KP_SC_INVALID_KEY          0xFE

#define     XLLP_KP_SC_A                    0x00
#define     XLLP_KP_SC_B                    0x10
#define     XLLP_KP_SC_C                    0x20
#define     XLLP_KP_SC_D                    0x30
#define     XLLP_KP_SC_E                    0x40
#define     XLLP_KP_SC_F                    0x50
#define     XLLP_KP_SC_G                    0x01
#define     XLLP_KP_SC_H                    0x11
#define     XLLP_KP_SC_I                    0x21
#define     XLLP_KP_SC_J                    0x31
#define     XLLP_KP_SC_K                    0x41
#define     XLLP_KP_SC_L                    0x51
#define     XLLP_KP_SC_M                    0x02
#define     XLLP_KP_SC_N                    0x12
#define     XLLP_KP_SC_O                    0x22
#define     XLLP_KP_SC_P                    0x32
#define     XLLP_KP_SC_Q                    0x42
#define     XLLP_KP_SC_R                    0x52
#define     XLLP_KP_SC_S                    0x03
#define     XLLP_KP_SC_T                    0x13
#define     XLLP_KP_SC_U                    0x23
#define     XLLP_KP_SC_V                    0x33
#define     XLLP_KP_SC_W                    0x43
#define     XLLP_KP_SC_X                    0x53
#define     XLLP_KP_SC_Y                    0x24
#define     XLLP_KP_SC_Z                    0x34

#define     XLLP_KP_SC_PERIOD               0x04
#define     XLLP_KP_SC_AT_SYMBOL    0x14  /* @ */
#define     XLLP_KP_SC_SLASH                0x44
#define     XLLP_KP_SC_BACKSLASH            0x54

#define     XLLP_KP_SC_HOME                 0x05
#define     XLLP_KP_SC_SHIFT                0x15
#define     XLLP_KP_SC_SPACE        0x25
#define     XLLP_KP_SC_SPACE_RSVD   0x35
#define     XLLP_KP_SC_BLUEKEY      0x45
#define     XLLP_KP_SC_BACK                 0x55

#define     XLLP_KP_SC_1                    0x70
#define     XLLP_KP_SC_2                    0x72
#define     XLLP_KP_SC_3                    0x74
#define     XLLP_KP_SC_4                    0x80
#define     XLLP_KP_SC_5                    0x82
#define     XLLP_KP_SC_6                    0x84
#define     XLLP_KP_SC_7                    0x90
#define     XLLP_KP_SC_8                    0x92
#define     XLLP_KP_SC_9                    0x94
#define     XLLP_KP_SC_0                    0xA2

#define     XLLP_KP_SC_SOFT1                0x62
#define     XLLP_KP_SC_SOFT2                0x63
#define     XLLP_KP_SC_SEND                 0x60
#define     XLLP_KP_SC_END                  0x61
// Navigation center scan codes
#define     XLLP_KP_SC_N_UP                 0x06
#define     XLLP_KP_SC_N_DOWN               0x16
#define     XLLP_KP_SC_N_LEFT               0x26
#define     XLLP_KP_SC_N_RIGHT              0x36
#define     XLLP_KP_SC_N_ACTION             0x46

#define     XLLP_KP_SC_SCROLL_PUSH          0x64

#define     XLLP_KP_SC_STAR     0xA0      /* * */
#define     XLLP_KP_SC_POUND        0xA4      /* # */
#define     XLLP_KP_SC_BANG     0x80      /* ! */
#define     XLLP_KP_SC_QMARK        0xA0      /* ? */
#define     XLLP_KP_SC_DOLLAR       0x81      /* $ */
#define     XLLP_KP_SC_AMPERSAND    0xA1      /* & */

#define     XLLP_KP_SC_COLON                0x82
#define     XLLP_KP_SC_SEMICOLON            0xA2
/*#define     XLLP_KP_SC_????       0x83 */
/*#define     XLLP_KP_SC_????       0xA3 */
#define     XLLP_KP_SC_TAB                  0x74
#define     XLLP_KP_SC_L_PAREN      0x84      /* (*/
#define     XLLP_KP_SC_R_PAREN              0x94
/*#define     XLLP_KP_SC_L_ARROW  ???   0xA4 */
#define     XLLP_KP_SC_ENTER        0xB4 /* Also called "RETURN"*/

#define     XLLP_KP_SC_SCROLL_UP            0x0A
#define     XLLP_KP_SC_SCROLL_DOWN          0x0B

// New keys for Zoar

#define     XLLP_KP_SC_RECORD               0x0D
#define     XLLP_KP_SC_DELETE               0x1C

#define     XLLP_KP_SC_AUX1                 0x19
#define     XLLP_KP_SC_AUX2                 0x1A
#define     XLLP_KP_SC_AUX3                 0x1B

#define     XLLP_KP_SC_VOL_UP               0x1D
#define     XLLP_KP_SC_VOL_DN               0x1E

// New navigation-station chord scan codes

#define     XLLP_KP_SC_N_UP_LEFT              0xA5
#define     XLLP_KP_SC_N_UP_RIGHT             0xA6
#define     XLLP_KP_SC_N_DOWN_LEFT            0xA7
#define     XLLP_KP_SC_N_DOWN_RIGHT           0xA8
#define     XLLP_KP_SC_N_ACTION_UP            0xA9
#define     XLLP_KP_SC_N_ACTION_DOWN          0xAA
#define     XLLP_KP_SC_N_ACTION_LEFT          0xAB
#define     XLLP_KP_SC_N_ACTION_RIGHT         0xAC
#define     XLLP_KP_SC_N_ACTION_UP_LEFT       0xAD
#define     XLLP_KP_SC_N_ACTION_UP_RIGHT      0xAE
#define     XLLP_KP_SC_N_ACTION_DOWN_LEFT     0xAF
#define     XLLP_KP_SC_N_ACTION_DOWN_RIGHT    0xB5

typedef enum {
    XLLP_RESOURCE_I2C = 0,
    XLLP_RESOURCE_MFPR,          // MFP registers
    XLLP_RESOURCE_MFPR_RM,       // MFP resource manager
    XLLP_RESOURCE_ID_COUNT,
    XLLP_RESOURCE_CLK_EN
} XLLP_PROTECTED_RESOURCES_ID_T; // more IDs might be added

static XLLP_UINT32_T xllp_keypad_mfp_list []={
    XLLP_MFP_KP_MKIN_0_OFFSET,
    XLLP_MFP_KP_MKIN_1_OFFSET,
    XLLP_MFP_KP_MKIN_2_OFFSET,
    XLLP_MFP_KP_MKIN_3_OFFSET,
    XLLP_MFP_KP_MKIN_4_OFFSET,
    XLLP_MFP_KP_MKIN_5_OFFSET,
    XLLP_MFP_KP_MKIN_6_OFFSET,
    XLLP_MFP_KP_MKIN_7_OFFSET,
    XLLP_MFP_KP_MKOUT_0_OFFSET,
    XLLP_MFP_KP_MKOUT_1_OFFSET,
    XLLP_MFP_KP_MKOUT_2_OFFSET,
    XLLP_MFP_KP_MKOUT_3_OFFSET,
    XLLP_MFP_KP_MKOUT_4_OFFSET,
    XLLP_MFP_KP_MKOUT_5_OFFSET,
    XLLP_MFP_KP_MKOUT_6_OFFSET,
    XLLP_MFP_KP_MKOUT_7_OFFSET,
    XLLP_MFP_PIN_EOLIST_MARKER
};/*end of xllp_keypad_mfp_listtypedef struct*/

static XLLP_MFP_ALT_FN_T xllp_keypad_af_list []={
    XLLP_MFP_KP_MKIN_0_AF,    /*MKIN_0*/
    XLLP_MFP_KP_MKIN_1_AF,    /*MKIN_1*/
    XLLP_MFP_KP_MKIN_2_AF,    /*MKIN_2*/
    XLLP_MFP_KP_MKIN_3_AF,    /*MKIN_3*/
    XLLP_MFP_KP_MKIN_4_AF,    /*MKIN_4*/
    XLLP_MFP_KP_MKIN_5_AF,    /*MKIN_5*/
    XLLP_MFP_KP_MKIN_6_AF,    /*MKIN_6*/
    XLLP_MFP_KP_MKIN_7_AF,    /*MKIN_7*/
    XLLP_MFP_KP_MKOUT_0_AF,   /*MKOUT_0*/
    XLLP_MFP_KP_MKOUT_1_AF,   /*MKOUT_1*/
    XLLP_MFP_KP_MKOUT_2_AF,   /*MKOUT_2*/
    XLLP_MFP_KP_MKOUT_3_AF,   /*MKOUT_3*/
    XLLP_MFP_KP_MKOUT_4_AF,   /*MKOUT_4*/
    XLLP_MFP_KP_MKOUT_5_AF,   /*MKOUT_5*/
    XLLP_MFP_KP_MKOUT_6_AF,   /*MKOUT_6*/
    XLLP_MFP_KP_MKOUT_7_AF,   /*MKOUT_7*/
};/*end of xllp_keypad_af_list*/

static XLLP_MFP_DRIVE_STRENGTH_T xllp_keypad_ds_list []={
    /*
       FIX ME
Note: The keypad is not in the list of devices that
may require special drive strengths
*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_0*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_1*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_2*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_3*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_4*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_5*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_6*/
    XLLP_MFP_DEFAULT_DS,   /*MKIN_7*/
    XLLP_MFP_DEFAULT_DS,   /*MKOUT_0*/
    XLLP_MFP_DEFAULT_DS,   /*MKOUT_1*/
    XLLP_MFP_DEFAULT_DS,   /*MKOUT_2*/
    XLLP_MFP_DEFAULT_DS,   /*MKOUT_3*/
    XLLP_MFP_DEFAULT_DS,   /*MKOUT_4*/
    XLLP_MFP_DEFAULT_DS,   /*MKOUT_5*/
    XLLP_MFP_DEFAULT_DS,   /*MKOUT_6*/
    XLLP_MFP_DEFAULT_DS    /*MKOUT_7*/
};/*end of xllp_keypad-ds_list*/

/*
   For the sake of speed and simplicity, this table is configured so that the
   single-closure matrix scan codes are placed using an MK_INn (row) by
   MK_OUTm (column) format.  That will permit direct use of the KPAS
   register's lower 8 bits, which yield that indexing.
   Multiclosure (chorded) scan codes are processed in-line by the multipress parser
   */
/*
Note: ific
Unassigned cells filled with 0xFE (XLLP_KP_SC_INVALID_KEY)
*/
#define XLLP_KP_MAX_SINGLE_SCAN_CODES 64

/*
   we treat
   key CONTACT as XLLP_KP_SC_AUX1;
   key CALENDAR as XLLP_KP_SC_AUX2;
   key EMAIL as XLLP_KP_SC_AUX3
   */
static XLLP_UINT8_T xllpKpScanCodeLut[XLLP_KP_MAX_SINGLE_SCAN_CODES] =
{
    /*IN0*/
    /*OUT0 */XLLP_KP_SC_A,
    /*OUT1 */XLLP_KP_SC_B,
    /*OUT2 */XLLP_KP_SC_C,
    /*OUT3 */XLLP_KP_SC_AUX1,
    /*OUT4 */XLLP_KP_SC_AUX3,
    /*OUT5 */XLLP_KP_SC_D,
    /*OUT6 */XLLP_KP_SC_SOFT1,
    /*OUT7 */XLLP_KP_SC_N_UP,

    /*IN1*/
    /*OUT0 */XLLP_KP_SC_E,
    /*OUT1 */XLLP_KP_SC_F,
    /*OUT2 */XLLP_KP_SC_G,
    /*OUT3 */XLLP_KP_SC_1,
    /*OUT4 */XLLP_KP_SC_3,
    /*OUT5 */XLLP_KP_SC_H,
    /*OUT6 */XLLP_KP_SC_SOFT2,
    /*OUT7*/XLLP_KP_SC_N_DOWN,

    /*IN2*/
    /*OUT0 */XLLP_KP_SC_I,
    /*OUT1 */XLLP_KP_SC_J,
    /*OUT2 */XLLP_KP_SC_K,
    /*OUT3 */XLLP_KP_SC_4,
    /*OUT4 */XLLP_KP_SC_6,
    /*OUT5 */XLLP_KP_SC_L,
    /*OUT6 */XLLP_KP_SC_HOME ,
    /*OUT7 */XLLP_KP_SC_N_LEFT ,

    /*IN3*/
    /*OUT0 */XLLP_KP_SC_M,
    /*OUT1 */XLLP_KP_SC_N,
    /*OUT2 */XLLP_KP_SC_O,
    /*OUT3 */XLLP_KP_SC_7,
    /*OUT4 */XLLP_KP_SC_9,
    /*OUT5 */XLLP_KP_SC_P ,
    /*OUT6 */XLLP_KP_SC_END ,
    /*OUT7 */XLLP_KP_SC_N_RIGHT,

    /*IN4*/
    /*OUT0 */XLLP_KP_SC_AUX2,
    /*OUT1 */XLLP_KP_SC_2,
    /*OUT2 */XLLP_KP_SC_5,
    /*OUT3 */XLLP_KP_SC_8,
    /*OUT4*/XLLP_KP_SC_0,
    /*OUT5 */XLLP_KP_SC_SPACE,
    /*OUT6 */XLLP_KP_SC_SCROLL_PUSH,
    /*OUT7 */0xFE,

    /*IN5*/
    /*OUT0 */XLLP_KP_SC_Q,
    /*OUT1 */XLLP_KP_SC_R,
    /*OUT2 */XLLP_KP_SC_S,
    /*OUT3 */XLLP_KP_SC_STAR,
    /*OUT4 */XLLP_KP_SC_POUND,
    /*OUT5 */XLLP_KP_SC_T,
    /*OUT6 */XLLP_KP_SC_SEND,
    /*OUT7 */XLLP_KP_SC_N_ACTION,

    /*IN6*/
    /*OUT0 */XLLP_KP_SC_U,
    /*OUT1 */XLLP_KP_SC_V,
    /*OUT2 */XLLP_KP_SC_W,
    /*OUT3 */XLLP_KP_SC_SHIFT,
    /*OUT4 */XLLP_KP_SC_DELETE,
    /*OUT5 */XLLP_KP_SC_X,
    /*OUT6 */XLLP_KP_SC_BACK,
    /*OUT7 */XLLP_KP_SC_VOL_UP,

    /*IN7*/
    /*OUT0 */0xFE,
    /*OUT1 */XLLP_KP_SC_Y,
    /*OUT2 */XLLP_KP_SC_Z,
    /*OUT3 */0xFE,
    /*OUT4 */0xFE,
    /*OUT5 */0xFE,
    /*OUT6 */XLLP_KP_SC_RECORD,
    /*OUT7 */XLLP_KP_SC_VOL_DN,
};  /*xllpKpScanCodeLutLower*/

#define     XLLP_KEYPAD_COLS_NUM      8
#define     XLLP_KEYPAD_ROWS_NUM     8

//==================================
//          Function Declaration
//==================================
XLLP_STATUS_T XllpMfpSetAfDs_List (
        P_XLLP_VUINT32_T        pMfpRegBase,
        P_XLLP_UINT32_T         pMfpOffsetList,
        P_XLLP_MFP_ALT_FN_T     pAfCodeList,
        P_XLLP_MFP_DRIVE_STRENGTH_T pDriveStrengthList);

XLLP_STATUS_T XllpMfpResourceManagerInit (P_XLLP_MFP_RM_DB_ID_T pMfpRmDb);
XLLP_STATUS_T xllp_keypad_config_mfp(
        P_XLLP_VUINT32_T pMfpRegBase,
        P_XLLP_MFP_RM_DB_ID_T pMfpRmDb);
XLLP_STATUS_T XllpLock(XLLP_PROTECTED_RESOURCES_ID_T Xllp_RegisterID);
XLLP_STATUS_T XllpUnlock(XLLP_PROTECTED_RESOURCES_ID_T Xllp_LockID);

/*-----------------------------------------------------------------------
Function:  xllp_keypad_config_mfp
Purpose:   This function configures the MFP for keypad
Returns:   XLLPSTATUS_T
Type No:   I/F flat 1
--------------------------------------------------------------------------*/
XLLP_STATUS_T xllp_keypad_config_mfp(
        P_XLLP_VUINT32_T pMfpRegBase,
        P_XLLP_MFP_RM_DB_ID_T pMfpRmDb)
{
    XLLP_STATUS_T retval = XLLP_STATUS_SUCCESS;
    retval =  XllpMfpResourceManager_List(
            pMfpRmDb,
            xllp_keypad_mfp_list,
            XLLP_MFP_RM_ID_XLLP_KEYPAD ,
            XLLP_SET);

    if ( XLLP_STATUS_SUCCESS != retval) {
        return retval ;
    }

    /*
       Lock MFPR block until finished with all MFPRs.
       Don't forget to unlock for early returns, too.*/

    XllpLock(XLLP_RESOURCE_MFPR);
    /*Assign the Alternate Functions and Drive Strengths for each keypad MFP.*/
    retval = XllpMfpSetAfDs_List(
            pMfpRegBase,
            xllp_keypad_mfp_list,
            xllp_keypad_af_list,
            xllp_keypad_ds_list);

    if ( XLLP_STATUS_SUCCESS != retval) {
        XllpUnlock(XLLP_RESOURCE_MFPR);
        return retval ;
    }

    return XLLP_STATUS_SUCCESS;
}/*end xllp_keypad_config_mfp*/

void dumpKPMFP()
{
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_0_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_0_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_1_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_1_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_2_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_2_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_3_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_3_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_4_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_4_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_5_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_5_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_6_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_6_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKIN_7_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKIN_7_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_0_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_0_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_1_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_1_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_2_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_2_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_3_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_3_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_4_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_4_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_5_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_5_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_6_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_6_OFFSET)));
    printf("%x = %x\n",(0x40E10000+XLLP_MFP_KP_MKOUT_7_OFFSET),*((volatile  unsigned long *)(0x40E10000+XLLP_MFP_KP_MKOUT_7_OFFSET)));
}

void wls_keypad_init()
{
    P_XLLP_VUINT32_T    pMfpRegBase = (P_XLLP_VUINT32_T)0x40E10000;
    P_XLLP_MFP_RM_DB_ID_T pMfpRMDb = (P_XLLP_MFP_RM_DB_ID_T) 0x5c012000;
    XLLP_KEYPAD_REGS * pKeyPadRegs = (XLLP_KEYPAD_REGS *)0x41500000;

    CKENA |= CKENA_14_KEYPAD;
    ostdelay(50);
    AD2D0SR =  XLLP_ADxD0_KP;
    AD2D0ER |= XLLP_ADxD0_KP;

    //configurate keypad
    XllpMfpResourceManagerInit(pMfpRMDb);

    xllp_keypad_config_mfp(pMfpRegBase, pMfpRMDb);

    xllp_keypad_config_controller(
            pKeyPadRegs,
            XLLP_TRUE,
            0,
            0,
            XLLP_KEYPAD_ROWS_NUM,
            XLLP_KEYPAD_COLS_NUM);
    dumpKPMFP();
    return;
}

char wls_keypad_getkey()
{
    XLLP_UINT32_T   kp_status;
    XLLP_UINT8_T    key = 0x54;
    XLLP_KEYPAD_REGS  *v_pkeypad_regs = (XLLP_KEYPAD_REGS *)0x41500000;
    kp_status = v_pkeypad_regs->kpControlReg;

    /*
       Process matrix first to capture scroll
       wheel press rather than interpreting it
       as a rotate, which can happen unintentionally.
       */
 //   printf("kp_status %x\n",kp_status);
    if(kp_status & MATRIX_INTR_BIT) {
        read_scan_code_automatically(v_pkeypad_regs,&key);
//        printf("read_scan_code_automatically 0x%x\n",key);
        if(key == NO_KEY) {
            key = NO_KEY;
            return(XLLP_STATUS_FAILURE);
        }
        key = xllpKpScanCodeLut[key];
    }else if(kp_status & DIRECT_INTR_BIT ) {

        read_direct_keys(v_pkeypad_regs,&key);
        printf("read_direct_keys %d\n",key);
    }

    return key;
}

/*-------------------------------------------------------------------------
Function: read_direct_keys
Purpose:  This function looks for any Thumbwheel movement or
button press and returns a scan code.
Returns:  success/failure.
type no:  I/F proc 2
---------------------------------------------------------------------------*/
XLLP_STATUS_T  read_direct_keys(
        XLLP_KEYPAD_REGS *v_pkeypad_regs,
        XLLP_UINT8_T *key)
{
    XLLP_UINT32_T curr_count,save_kp_rotary_encoder_count_reg;
    static XLLP_UINT32_T prev_count = START_VALUE;

    save_kp_rotary_encoder_count_reg =
        v_pkeypad_regs->kpRotaryEncoderCountReg;
    curr_count = save_kp_rotary_encoder_count_reg & COUNT_MASK;

    if(save_kp_rotary_encoder_count_reg & OVERFLOW_ROTARY_ENC_0)
    {
        v_pkeypad_regs->kpRotaryEncoderCountReg = START_VALUE;
        prev_count   = START_VALUE;
        *key    = SCAN_CODE_SCROLL_UP;/* Scroll Up*/
    }
    else if(save_kp_rotary_encoder_count_reg & UNDERFLOW_ROTARY_ENC_0)
    {
        v_pkeypad_regs->kpRotaryEncoderCountReg = START_VALUE;
        prev_count   = START_VALUE;
        *key    = SCAN_CODE_SCROLL_DOWN; /* Scroll Down*/
    }
    else if(curr_count > prev_count)
    {
        *key    = SCAN_CODE_SCROLL_UP;
        prev_count   = curr_count;/* Scroll Up*/
    }
    else if(curr_count < prev_count)
    {
        *key    = SCAN_CODE_SCROLL_DOWN;
        prev_count   = curr_count; /* Scroll Down*/
    }

    return XLLP_STATUS_SUCCESS;
}//end function read_direct_keys

/*---------------------------------------------------------------------------
Function: read_scan_code_automatically
Purpose:This functions reads the scan code from the KeyPad controller triggered by
setting of the ASACT bit in the KeyPad Control register. If there is a valid key
detected then it returns the scan code.
Returns:  success/failure.
type no:  I/F proc 3
-----------------------------------------------------------------------------*/

XLLP_STATUS_T read_scan_code_automatically(
        XLLP_KEYPAD_REGS *v_pkeypad_regs,
        XLLP_UINT8_T    *key_index)
{
    XLLP_BOOL_T retval = XLLP_STATUS_FAILURE;  /* Default to failure indication*/
    XLLP_UINT32_T   num_of_keys_pressed=0;
    int     scan_code_index;
    /* minimize slow hardware accesses*/
    XLLP_UINT32_T   kp_asr_tmp;

    *key_index = NO_KEY;  /* Default to failure indication*/

    num_of_keys_pressed =
        ((v_pkeypad_regs->kpAutomaticScanReg & MULTI_KEYS_PRESS)>>26);

    if(num_of_keys_pressed == 1)
    {
        kp_asr_tmp = v_pkeypad_regs->kpAutomaticScanReg;
        /* test for valid data*/
        if ((ROW_SELECTED_MASK  == (kp_asr_tmp & ROW_SELECTED_MASK)) ||
                (COL_SELECTED_MASK  == (kp_asr_tmp & COL_SELECTED_MASK))){
            /* If either row or column field == 0xFF,
               data are invalid*/
            *key_index = NO_KEY;
        }else{
            /* if not invalid, 3 bits of data for each field.
               Compress to 6 bits for index into
               the 64-entry LUT.*/
            scan_code_index =
                ((kp_asr_tmp & ROW_SELECTED_MASK) >> 1) |
                (kp_asr_tmp &  COL_SELECTED_MASK);

            *key_index= scan_code_index;

            retval = XLLP_STATUS_SUCCESS;
        }
    }else {
        /*current do not support multi key press*/
        *key_index= NO_KEY;
    }/*end of numofkeypressed ==1*/
    return retval;
}

/*---------------------------------------------------------------------------
Function:  xllp_keypad_config_controller
Purpose:   This function configures the keypad controller
Returns:   XLLPSTATUS_T
Type No:   I/F proc 1
-----------------------------------------------------------------------------*/
void xllp_keypad_config_controller(
        XLLP_KEYPAD_REGS *  p_key_pad_regs,
        XLLP_BOOL_T use_default_debounces,
        XLLP_UINT8_T    matix_debounce_ms,
        XLLP_UINT8_T    direct_debounce_ms,
        XLLP_UINT8_T    max_row,
        XLLP_UINT8_T    max_col)
{
    /*Init the control regs for direct keys*/

    p_key_pad_regs->kpControlReg = (
            ((max_row-1)<< 26) |
            ((max_col-1) << 23) |
            MAT_SCAN_LINE0 |
            MAT_SCAN_LINE1 |
            MAT_SCAN_LINE2 |
            MAT_SCAN_LINE3 |
            MAT_SCAN_LINE4 |
            MAT_SCAN_LINE5 |
            MAT_SCAN_LINE6 |
            MAT_SCAN_LINE7 |
            AUTO_SCAN_ON_ACTIVITY |
            MATRIX_INTR_ENABLE |
            MATRIX_KP_ENABLE |
            ROTARY_ENCODER_ZERO_DEB |
            /*      DIRECT_KP_INTR_ENABLE | */
            DIRECT_KEY_NUMS |
            DIRECT_KP_ENABLE |
            ROTARY_ENCODER_0_ENABLE) ;

    p_key_pad_regs->kpRotaryEncoderCountReg = START_VALUE;

    if (use_default_debounces) {
        p_key_pad_regs->kpKeyDebounceInterval = (
                4 << 8 |
                4);
    }
    else {
        p_key_pad_regs->kpKeyDebounceInterval = (
                (direct_debounce_ms<<8)
                | matix_debounce_ms);
    }
}

